var _assert = require('assert');

var _assert2 = _interopRequireDefault(_assert);

var _jsonwebtoken = require('jsonwebtoken');

var _jsonwebtoken2 = _interopRequireDefault(_jsonwebtoken);

var _thinkHelper = require('think-helper');

var _thinkHelper2 = _interopRequireDefault(_thinkHelper);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }

/**
 * 业务层基类
 */
class BaseService extends think.Service {
  /**
     * 角色数据范围过滤
     * tableName   (必传)当前过滤的表名
     * userInfo  (必传)用户信息
     * option 选项(可选){
     *    attributes:`field1,field2,field3`,或者['field1','field2','field3']
             page:{
                 start:0,  //第几页
                 limit:0   //每页显示多少条
             }
     * }
     * 返回false代表没有数据权限过滤
     */
  dataScopeFilter(tableName, userInfo, option) {
    var _this = this;

    return _asyncToGenerator(function* () {
      (0, _assert2.default)(typeof tableName === 'string', 'tableName must be a String');
      (0, _assert2.default)(ObjectUtils.isObject(userInfo), 'userInfo must be a Object');
      const defaultOption = {
        // attributes: `${tableName}.*`,
        attributes: '*',
        ORG_TABLE_NAME: 'sys_org',
        USER_TABLE_NAME: 'sys_user'
        // page:{
        //     start:null,
        //     limit:null
        // }
      };
      const DB = _this.db;
      const model = DB[tableName];
      const orgModel = DB['sys_org'];
      (0, _assert2.default)(model, 'table does not exist');
      const { userId, orgId, roleList } = userInfo;
      const administrator = think.config('administrator');
      option = _thinkHelper2.default.extend({}, defaultOption, option);
      const ORG_TABLE_NAME = option.ORG_TABLE_NAME;
      const USER_TABLE_NAME = option.USER_TABLE_NAME;
      // if (option.attributes.includes('*')) {
      //     option.attributes = `${tableName}.*`;
      // }
      const attributes = option.attributes;
      let pageStr = '';
      if ('page' in option) {
        const start = option.page.start;
        const limit = option.page.limit;
        if (start && limit) {
          pageStr = ` limit ${(start - 1) * limit},${limit}`;
        }
      }
      // 数据范围（1：所有数据；2：所在部门及以下数据；3：所在部门数据；4：仅本人数据；5：按明细设置）
      /**
           * 1、所有数据： 无where条件,直接返回所有数据。
           * 2、所在部门及以下数据   like当前用户所在部门的parent_ids + 当前用户的'部门id, or部门id=部门id'
           * 3、所在部门数据      =当前用户的部门id
           * 4、仅本人数据　　　　仅跟自己相关的业务数据。
           * 5、按明细设置 跨机构授权,多个角色的授权为并集的关系。
           */

      // 数据权限过滤，多个角色权限范围之间为或者关系。
      const dataScopeArry = yield _this.getRoleDataScope(roleList);
      if (dataScopeArry.length === 0) {
        return false;
      }
      const dataScopeNum = ArrayUtils.findArrayMin(dataScopeArry);
      let sql = 'SELECT ';
      let field = attributes;
      // let newAttr;
      if (Array.isArray(attributes)) {
        // newAttr = attributes.map((item, index, arr) => {
        //     return `${tableName}.${item}`;
        // });
        field = attributes.join();
      }
      sql += field;
      // 如果是超级管理员或者数据权重为1，则跳过数据权限过滤
      if (dataScopeNum === 1 || administrator.includes(userId)) {
        sql += ` FROM ${tableName}`;
        pageStr ? sql += pageStr : sql += '';
        return _this.CrudService.querySql(sql);
      }

      let orgIds = null;
      let customWhereStr = '';
      // 如果存在自定义授权，则先构造自定义where条件
      if (dataScopeArry.includes(5)) {
        orgIds = yield _this.findCustomAuthOrgIds(roleList);
        customWhereStr = ` OR org.id in(${orgIds})`;
      }
      // 根据表名构造表连接，用户表,机构表,业务表。
      if (tableName === USER_TABLE_NAME) {
        sql += ` FROM ${tableName} us INNER JOIN ${ORG_TABLE_NAME} org ON us.org_id = org.id`;
      } else if (tableName === ORG_TABLE_NAME) {
        sql += ` FROM ${tableName} org`;
      } else {
        sql += ` FROM ${tableName} INNER JOIN ${USER_TABLE_NAME} us ON ${tableName}.create_by = us.id INNER JOIN ${ORG_TABLE_NAME} org ON us.org_id = org.id`;
      }
      // 根据数据权限构造不同的where条件
      switch (dataScopeNum) {
        case 2:
          // 所在部门及以下
          const object = yield orgModel.findById(orgId, {
            attributes: ['parent_ids']
          });
          const orgParentIds = object.parent_ids;
          sql += ` WHERE org.parent_ids LIKE '%${orgParentIds}${orgId},%' or org.id=${orgId}`;
          break;
        case 3:
          // 所在部门
          sql += ` WHERE org.id = ${orgId}`;
          break;

        case 4:
          // 本人数据
          if (tableName === USER_TABLE_NAME) {
            sql += ` WHERE us.id="${userId}"`;
          } else if (tableName === ORG_TABLE_NAME) {
            sql += ` WHERE org.id="${orgId}"`;
          } else {
            sql += ` WHERE ${tableName}.create_by="${userId}"`;
            // customWhereStr ? sql = `SELECT ${field} FROM ${tableName} INNER JOIN ${USER_TABLE_NAME} us ON ${tableName}.create_by = us.id INNER JOIN ${ORG_TABLE_NAME} org ON us.org_id = org.id WHERE ${tableName}.create_by="${userId}" ${customWhereStr}` : sql = `SELECT ${field} FROM ${tableName} WHERE create_by="${userId}"`;
          }
          break;
        case 5:
          // 自定义授权
          customWhereStr = ` WHERE org.id in(${orgIds})`;
          break;
      }

      sql += customWhereStr;
      sql += pageStr;
      const list = yield _this.CrudService.querySql(sql);
      if (pageStr) {
        return {
          rows: list,
          count: option.page.limit
        };
      }
      return list;
    })();
  }

  /**
     * 查询自定义权限的机构ids
     * @param roleList
     * @returns {Promise<string>}
     * @private
     */
  findCustomAuthOrgIds(roleList) {
    var _this2 = this;

    return _asyncToGenerator(function* () {
      const Op = _this2.db.Sequelize.Op;
      const result = yield _this2.db['sys_role'].findAll({
        where: { id: { [Op.in]: roleList } },
        attributes: ['auth_org_ids'],
        raw: true
      });
      let arry = [];
      for (const value of result) {
        if (!think.isEmpty(value.auth_org_ids)) {
          arry = arry.concat(value.auth_org_ids.split(','));
        }
      }
      const orgIds = ArrayUtils.unique(arry).join();
      return orgIds;
    })();
  }

  /**
     * 查询自定义权限的机构ids
     * @param roleList
     * @returns {Promise<Array>}
     * @private
     */
  findCustomAuthOrgIdsArray(roleList) {
    var _this3 = this;

    return _asyncToGenerator(function* () {
      const Op = _this3.db.Sequelize.Op;
      const result = yield _this3.db['sys_role'].findAll({
        where: { id: { [Op.in]: roleList } },
        attributes: ['auth_org_ids'],
        raw: true
      });
      let arry = [];
      for (const value of result) {
        if (!think.isEmpty(value.auth_org_ids)) {
          arry = arry.concat(value.auth_org_ids.split(','));
        }
      }
      const orgIds = ArrayUtils.unique(arry);
      return orgIds;
    })();
  }

  /**
     * 数据过滤，返回where条件
     * 如果返回1，则在业务代码里没有where条件
     * 如果返回4,则目标表里带create_by=userid的条件
     * 否则返回正确的where条件在sys_org表里
     * @param userInfo
     * @param isOrm
     * @returns {Promise<*>}
     */
  getDataScopeWhere(userInfo, isOrm) {
    var _this4 = this;

    return _asyncToGenerator(function* () {
      const db = _this4.db;
      const Op = db.Sequelize.Op;
      const orgModel = db['sys_org'];
      const administrator = think.config('administrator');
      const { roleList, orgId } = userInfo;
      let whereObj = {};
      let whereStr = '';
      if (!think.isEmpty(roleList) && !think.isEmpty(orgId)) {
        const dataScopeNumAry = yield _this4.getRoleDataScope(roleList);
        const dataScopeNum = ArrayUtils.findArrayMin(dataScopeNumAry);
        // 如果是超级管理员或者数据权重为1，则跳过数据权限过滤
        if (dataScopeNum === 1 || administrator.includes(userInfo)) {
          return 1;
        }
        // 如果存在自定义授权，则先构造自定义where条件

        let otherWhere = null;
        if (dataScopeNumAry.includes(5)) {
          const orgIds = yield _this4.findCustomAuthOrgIdsArray(roleList);
          otherWhere = { id: { [Op.in]: orgIds } };
          // orgIds = await this.findCustomAuthOrgIds(roleList);
          // customWhereStr = ` OR org.id in(${orgIds})`
        }
        switch (dataScopeNum) {
          case 2:
            const object = yield orgModel.findById(orgId, {
              attributes: ['parent_ids']
            });
            const orgParentIds = object.parent_ids;
            if (isOrm) {
              if (otherWhere) {
                whereObj = {
                  [Op.or]: [{ parent_ids: { [Op.like]: `%${orgParentIds}${orgId},%` } }, { id: orgId }, otherWhere]
                };
              } else {
                whereObj = {
                  [Op.or]: [{ parent_ids: { [Op.like]: `%${orgParentIds}${orgId},%` } }, { id: orgId }]
                };
              }

              return whereObj;
            }
            whereStr = `WHERE sys_org.parent_ids LIKE '%${orgParentIds}${orgId},%' or sys_org.id=${orgId}`;
            return whereStr;
          case 3:
            if (isOrm) {
              if (otherWhere) {
                whereObj = {
                  [Op.or]: [{ id: orgId }, otherWhere]
                };
              } else {
                whereObj = { id: orgId };
              }

              return whereObj;
            }
            whereStr = `WHERE sys_org.id = ${orgId}`;
            return whereStr;
          case 4:
            return 4;
          case 5:
            if (otherWhere) {
              whereObj = otherWhere;
            }
            return whereObj;
        }
      }
      return null;
    })();
  }

  /**
     * 扫描所有用户，根据权限标识查询有权限用户的id,
     * @returns {Array}
     */
  getAllUserAuthByPermission(permission) {
    var _this5 = this;

    return _asyncToGenerator(function* () {
      const allUserInfo = [];
      const queue = []; // 队列人员
      const roleUserIds = yield _this5.db['sys_role_user'].findAll({ group: 'userid', attributes: ['userid'] });
      for (const value of roleUserIds) {
        allUserInfo.push((yield _this5.getUserInfo(value.userid)));
      }
      for (const value of allUserInfo) {
        const authVal = value.menuList.find(function (item) {
          return item.permission === permission;
        });
        if (authVal) {
          queue.push(value.id);
        }
      }
      return queue;
    })();
  }

  /**
     * 获取用户完全信息
     * @param userId
     * @returns {Promise<{Object}>}
     */
  getUserInfo(userId) {
    var _this6 = this;

    return _asyncToGenerator(function* () {
      (0, _assert2.default)(typeof userId === 'string' && userId, 'userId must not null && is String');
      const user = yield _this6.db['sys_user'].findOne({
        where: {
          id: userId
        },
        attributes: { exclude: ['password', 'del_flag'] }
      });
      const role = yield _this6.db['sys_role_user'].findAll({
        where: {
          userid: userId
        },
        attributes: ['roleid']
      });
      const roleIds = role.map(function (r) {
        return r.roleid;
      });
      const menuList = yield _this6.getRoleMenu(roleIds, userId);
      const userInfo = Object.assign({}, user.toJSON());
      userInfo.roleList = roleIds;
      userInfo.menuList = menuList;
      return userInfo;
    })();
  }

  getParentIdsByOrgId(orgId) {
    var _this7 = this;

    return _asyncToGenerator(function* () {
      return _this7.db['sys_org'].findOne({ where: { org_id: orgId } });
    })();
  }

  /**
     * 获取角色访问权限
     * @param roleList Array 角色ids
     * @returns {Promise<*>}
     */
  getRoleAuth(roleList) {
    var _this8 = this;

    return _asyncToGenerator(function* () {
      (0, _assert2.default)(Array.isArray(roleList), 'roleList type should eq "Array"');
      const roles = JSON.stringify(roleList).replace('[', '').replace(']', '');
      const sqlAuth = `SELECT mu.href FROM sys_menu mu INNER JOIN sys_role_menu rmu ON mu.id = rmu.menuid WHERE rmu.roleid in (${roles})`;
      const roleAuth = yield _this8.CrudService.querySql(sqlAuth);
      const obj = {
        href: []
      };
      for (const value of roleAuth) {
        obj.href.push(value.href);
      }
      return obj;
    })();
  }

  /**
     *
     * @param roleList
     * @returns {Promise<{required: boolean, message: string, trigger: string}[][]>}
     */
  getRoleDataScope(roleList) {
    var _this9 = this;

    return _asyncToGenerator(function* () {
      (0, _assert2.default)(Array.isArray(roleList), 'roleList type should eq "Array"');

      const roleDataScope = yield _this9.db['sys_role'].findAll({
        where: {
          id: {
            [_this9.db.Sequelize.Op.in]: roleList
          }
        },
        attributes: ['data_scope'],
        raw: true
      });
      return roleDataScope.map(function (item) {
        return item.data_scope;
      });
      // let roles = JSON.stringify(roleList).replace('[', '').replace(']', '');
      // let sql = `SELECT data_scope FROM sys_role WHERE id in(${roles})`;
      // const dataScopeList = await this.CrudService.querySql(sql);

      // const ary = dataScopeList.map((item) => {
      //     return item.data_scope;
      // });
      // return ary;
      // if (ary.includes(5) && ary.length > 1) {
      //     return [Number(ArrayUtils.findArrayMin(ary)), 5]
      // }
      // return Number(ArrayUtils.findArrayMin(ary));
    })();
  }

  /**
     * 根据角色ids获取角色菜单列表
     * @param roleList Array  角色ids
     * @param userId  String userId
     * @returns {Promise<*>}
     */
  getRoleMenu(roleList, userId) {
    var _this10 = this;

    return _asyncToGenerator(function* () {
      (0, _assert2.default)(Array.isArray(roleList), 'roleList type should eq "Array"');
      (0, _assert2.default)(typeof userId === 'string', 'userId must be a String');
      const administrator = think.config('administrator');
      const roles = JSON.stringify(roleList).replace('[', '').replace(']', '');
      let sql = '';
      if (administrator.includes(userId)) {
        sql = `SELECT * FROM sys_menu WHERE menu_source=1 GROUP BY id ORDER BY menu_order`;
        // sql = `SELECT * FROM sys_menu WHERE is_show=1 AND menu_source=1`;
      } else {
        // sql = `SELECT * FROM sys_menu mu INNER JOIN sys_role_menu rmu ON mu.id = rmu.menuid WHERE rmu.roleid in (${roles}) AND is_show=1 AND menu_source=1`;
        sql = `SELECT * FROM sys_menu mu INNER JOIN sys_role_menu rmu ON mu.id = rmu.menuid WHERE rmu.roleid in (${roles}) AND menu_source=1 GROUP BY mu.id ORDER BY menu_order`;
      }

      return _this10.CrudService.querySql(sql);
    })();
  }

  /**
     * 根据用户信息生成一个token
     * @param userInfo
     * @returns {*}token
     */
  getToken(userInfo) {
    const tokenConfig = think.config('token');
    const privateKey = tokenConfig.privateKey; // （密钥）
    const expiresIn = tokenConfig.expiresIn;
    const token = _jsonwebtoken2.default.sign(userInfo, privateKey, {
      expiresIn: expiresIn // 过期时间
    });
    return token;
  }

  getTokenForApp(userInfo) {
    const tokenConfig = think.config('token');
    const privateKey = tokenConfig.privateKey; // （密钥）
    const expiresIn = tokenConfig.expiresInApp;
    const token = _jsonwebtoken2.default.sign(userInfo, privateKey, {
      expiresIn: expiresIn // 过期时间
    });
    return token;
  }

  /**
     *  根据机构id获取直属公司
     * @param user
     * @returns {Promise<Object>}
     */
  getUserDirectCompany(orgId) {
    var _this11 = this;

    return _asyncToGenerator(function* () {
      (0, _assert2.default)(orgId, 'orgId must be a not empty');
      const orgModel = _this11.db['sys_org'];
      const OP = _this11.db.sequelize.Op;
      let orgInfo = null;
      const orgResult = yield orgModel.findOne({
        where: {
          id: orgId
        },
        raw: true
      });
      if (!think.isEmpty(orgResult)) {
        // 如果当前用户的所在的组织机构是公司，则直接返回该公司。
        if (orgResult.org_type === 1) {
          return orgResult;
        }
        const parentIds = orgResult.parent_ids;
        if (parentIds) {
          const parentIdsAry = parentIds.substr(0, parentIds.length - 1).split(',');
          // 查询和过滤树路径上的所有组织机构，只返回公司信息
          const orgList = yield orgModel.findAll({
            where: {
              id: {
                [OP.in]: parentIdsAry
              },
              org_type: 1
            },
            raw: true
          });
          if (!think.isEmpty(orgList)) {
            // 将树路径字符串数组转成数字数组，方便后面比较。
            const numParentIdsAry = parentIdsAry.map(function (item) {
              return parseInt(item);
            });

            const orgIdsAry = orgList.map(function (item) {
              return item.id;
            });
            // 以树路径用为参考和公司数组做比较找出交集，数组最末尾的值就是当前用户的直属公司。
            const intersection = ArrayUtils.intersection(numParentIdsAry, orgIdsAry);
            orgInfo = orgList.filter(function (item) {
              return item.id === intersection[intersection.length - 1];
            });
          }
        }
      }
      if (Array.isArray(orgInfo)) {
        return orgInfo[0];
      }
      return orgInfo;
    })();
  }

  isAdmin(user) {
    if (!think.isEmpty(user)) {
      return think.config('administrator').includes(user.userId);
    }
    return null;
  }

  /**
     * 根据pinyin或汉字搜索记录
     */

  /**
     *  缓存角色权限
     * @param userId  用户Id     type: string
     * @param roleList 角色列表  type:array
     * @returns {Promise<void>}
     */
  // async cacheRolePermission(roleList, userId) {
  //     assert(Array.isArray(roleList), 'roleList type should eq "Array"');
  //     let roles = JSON.stringify(roleList);
  //     roles = roles.replace('[', '').replace(']', '');
  //     let sql = `SELECT mu.href, mu.permission, mu.menu_source, rl.data_scope FROM sys_menu mu INNER JOIN sys_role_menu rmu ON mu.id = rmu.menuid INNER JOIN sys_role rl ON rl.id = rmu.roleid WHERE rl.id in (${roles})`;
  //     try {
  //         let rolePermissionList = await this.CrudService.querySql(sql);
  //         // console.log(rolePermissionList);
  //         if (think.redis.isReady()) {
  //             const redisCli = think.redis.client;
  //             // think.redis.client.set(`userInfo:rolePerm:${userId}`, JSON.stringify(rolePermissionList), 'EX', expiresIn);
  //             redisCli.set(`userInfo:rolePerm:${userId}`, JSON.stringify(rolePermissionList));
  //         } else {
  //             throw new Error('连接redis失败')
  //         }
  //     } catch (e) {
  //         this.exceptionService.handleError(e);
  //     }
  //
  // }
}

module.exports = BaseService;